package material

import (
	"context"
	"fmt"
	"gitee.com/bobo-rs/idea-space-framework/framework/dao"
	"gitee.com/bobo-rs/idea-space-framework/framework/model"
	"gitee.com/bobo-rs/idea-space-framework/framework/model/entity"
	"gitee.com/bobo-rs/idea-space-framework/framework/service"
	"gitee.com/bobo-rs/idea-space-framework/pkg/config"
	"gitee.com/bobo-rs/idea-space-framework/pkg/core/models"
	"gitee.com/bobo-rs/idea-space-framework/pkg/core/services/material"
	"gitee.com/bobo-rs/idea-space-framework/pkg/ifile"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"strings"
)

const (
	MaterialSubDir        = `/material`
	MaterialSubDirExample = `/example/`
)

// SaveMaterialTemplate 保存-添加|编辑素材模板信息
func (m *sMaterial) SaveMaterialTemplate(ctx context.Context, req model.MaterialTemplateSaveInput) (tid uint, err error) {
	// 处理数据
	t := entity.MaterialTemplate{
		Id:           req.Id,
		TemplateName: req.TemplateName,
		LabelValues:  strings.Join(req.Values, "-"),
		CutWordsNum:  req.CutWordsNum,
		SellingLen:   req.SellingLen,
		VipType:      req.VipType,
		IdxStatus:    1, // 默认完成
	}
	// 补充操作人信息
	adminUser := service.User().GetAdminUser(ctx)
	if t.Id == 0 && adminUser != nil {
		t.Creator = adminUser.ManageName
		t.CreatorId = adminUser.Id
	}
	if adminUser != nil {
		t.Modified = adminUser.ManageName
	}
	// 保存数据
	err = dao.MaterialTemplate.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		r, err := tx.Ctx(ctx).Save(dao.MaterialTemplate.Table(), t)
		if err != nil {
			return err
		}
		// 插入ID
		id, err := r.LastInsertId()
		if err != nil {
			return gerror.Wrapf(err, `素材模板更新保存失败%s`, err.Error())
		}
		tid = uint(id)
		if len(req.Words) > 0 {
			// 保存素材文案列表
			err = m.SaveMaterialTemplateWords(ctx, tid, req.Words...)
			if err != nil {
				return err
			}
		}
		// 创建索引-队列消息索引
		_ = service.Label().SaveLabelIdx(ctx, tid, 0, t.LabelValues)
		return nil
	})
	if err != nil {
		return 0, err
	}
	// 刷新示例图
	_ = m.RefreshMaterialTemplateExampleImg(ctx, tid)
	return tid, nil
}

// DeleteMaterialTemplate 删除素材模板信息
func (m *sMaterial) DeleteMaterialTemplate(ctx context.Context, tid uint) error {
	if tid == 0 {
		return gerror.New(`素材模板ID不能为空`)
	}
	// 检测是否存在相关设计图
	if service.Space().CheckSpaceImageDetailExistsByTid(ctx, tid) {
		return gerror.New(`该模板生成一个或以上设计图，不允许直接删除，可下架`)
	}
	// 删除数据
	return dao.MaterialTemplate.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err := tx.Ctx(ctx).Delete(dao.MaterialTemplate.Table(), g.Map{
			dao.MaterialTemplate.Columns().Id: tid,
		})
		if err != nil {
			return gerror.Wrapf(err, `删除模板失败[%s]，请重试`, err.Error())
		}
		// 模板文案
		err = m.DeleteMaterialTemplateWords(ctx, tid)
		if err != nil {
			return err
		}
		// 删除索引
		return service.Label().DeleteLabelIdx(ctx, tid, 0)
	})
}

// AuditOrOffMaterialTemplate 审核或下架关闭素材模板信息
func (m *sMaterial) AuditOrOffMaterialTemplate(ctx context.Context, in model.MaterialTemplateAuditOrOffInput) error {
	if in.Id == 0 {
		return gerror.New(`素材模板ID不能为0`)
	}
	_, err := dao.MaterialTemplate.Ctx(ctx).
		Where(dao.MaterialTemplate.Columns().Id, in.Id).
		Data(g.Map{dao.MaterialTemplate.Columns().Status: in.Status}).
		Update()
	if err != nil {
		return gerror.Wrapf(err, `更新素材模板失败[%s]，请重试`, err.Error())
	}
	return nil
}

// RefreshMaterialTemplateExampleImg 刷新素材模板示例图
func (m *sMaterial) RefreshMaterialTemplateExampleImg(ctx context.Context, tid uint) error {
	// 获取素材模板文本列表
	var words []model.MaterialTemplateWordsBasicItem
	err := m.ProcessTemplateWordsListByTid(ctx, tid, &words)
	if err != nil {
		return err
	}

	// 处理合成设计图
	overlay, err := m.processMaterialDesignOverlay(ctx, tid, words...)
	if err != nil {
		return err
	}

	resp, err := material.New().MaterialDesignOverlays(*overlay)
	if err != nil {
		return err
	}

	columns := dao.MaterialTemplate.Columns()
	// 更新数据
	_, err = dao.MaterialTemplate.Ctx(ctx).
		Where(columns.Id, tid).
		Update(g.Map{columns.ExampleImg: resp[0].Src})
	if err != nil {
		return gerror.Wrapf(err, `更新示例模板图失败%s`, err.Error())
	}
	return nil
}

// GetMaterialConfigRaw 获取素材配置内容
func (m *sMaterial) GetMaterialConfigRaw(ctx context.Context) (item *model.MaterialConfigItem, err error) {
	// 实例配置
	rawConfig := config.New()
	uploadConfig, err := rawConfig.GetLocalUploadConfig(ctx)
	if err != nil {
		return nil, err
	}
	item = &model.MaterialConfigItem{
		Dir:     uploadConfig.Root + uploadConfig.Path + MaterialSubDir + MaterialSubDirExample,
		RootDir: strings.TrimPrefix(uploadConfig.Root, "."),
	}

	// 读取底图
	item.UnderImg, err = rawConfig.GetMaterialUnderImg(ctx)
	if err != nil {
		return nil, err
	}
	// 获取字体
	item.FontPath, err = rawConfig.GetFontPath(ctx)
	if err != nil {
		return nil, err
	}
	return
}

// processMaterialDesignOverlay 处理素材设计合成图片
func (m *sMaterial) processMaterialDesignOverlay(ctx context.Context, tid uint, words ...model.MaterialTemplateWordsBasicItem) (overlay *models.MaterialDesignOverlayItem, err error) {

	configRaw, err := m.GetMaterialConfigRaw(ctx)
	if err != nil {
		return nil, err
	}
	// 实例逻辑
	overlay = &models.MaterialDesignOverlayItem{
		TemplateId: tid,
		MaterialDesignSaveItem: models.MaterialDesignSaveItem{
			IsSave:   true,
			Dir:      ifile.MustUploadPath(MaterialSubDir + MaterialSubDirExample),
			Filename: fmt.Sprintf(`%d.png`, tid),
		},
		UnderSrc: ifile.RelaResourcePath(configRaw.UnderImg),
		FontPath: ifile.RelaResourcePath(configRaw.FontPath),
	}

	// 处理数据
	for _, word := range words {
		overlay.DrawMaterialWords = append(overlay.DrawMaterialWords, models.MaterialWordsItem{
			Src:           ifile.RelaResourcePath(word.Url), // 补充资源目录
			Text:          word.ExampleWords,
			MaterialX:     word.MaterialX,
			MaterialY:     word.MaterialY,
			MaterialColor: word.MaterialColor,
			LayerPosition: word.LayerPosition,
			FontSize:      word.WordsFont,
			TextFontColor: word.WordsFontColor,
			TextX:         word.WordsX,
			TextY:         word.WordsY,
			TextType:      word.WordsType,
		})
	}

	return
}
